#ifndef MARCHING_CUBES_HPP
#define MARCHING_CUBES_HPP

#include <map>


#include <Inventor/nodes/SoSeparator.h>
#include <Inventor/nodes/SoCoordinate3.h>
#include <Inventor/nodes/SoFaceSet.h>

#include "point.hpp"

#include "dexelfield.hpp"
#include "notifiers.hpp"

#include <string>

using std::map;
using std::string;



struct noderef //calculate unique reference of pointed node
{ noderef()
  {
  }
  
  noderef(long x, long y, long z, int i); // i points to destination
  operator size_t() const;
  void Set(long x, long y, long z, int i);
 
  long ix,iy,iz;
};


class Facetter // calculates triangle shape from dexefield by Marching Cubes
{
public:
  Facetter(){}
  
  Facetter(dexelfield *m);
  
  // SoSeparator* GetPolyModel();
  void facet(facet_note *tic=NULL);  // calculate! tic for process indication
  void facet_traverse(facet_note *tic=NULL); //another approarch. don't use it:)

  void refacet(double x0 ,double x1, //refacet part of the shape. use when model changed
	       double y0, double y1,
	       double z0, double z1,
	       facet_note *tic=NULL);
  
  void setbounds(double _xmin, double _xmax,
		 double _ymin, double _ymax,
		 double _zmin, double _zmax);

  void setseed(double _dx, double  _dy, double _dz); //set size of single "cube"
  
  
    
  SoSeparator* Result()
  {
    return result;
  }
  
 
private:

  body_state test_state(double x,double y, double z);
  
  point intersect(noderef n1, noderef n2);
  point intersect(double x1,double y1, double z1,
		  double x2,double y2, double z2);
  
  
  void facet_cube(long ix,long iy, long iz);

  void facet_cube_traverse(long ix,long iy,long iz,
			   SoCoordinate3 *coords,
			   SoFaceSet *faces,
			   long &vert, long &tri);
 
  map<size_t,short> nodes;
  map<size_t,point> edges;

  map<size_t,SoSeparator*>  tetras;
  map<size_t,SoSeparator*>  cubes;

  SoSeparator* result;

  double dx,dy,dz;
  
  double volume_quant;
  dexelfield *model;

  double
  xmin, ymin, zmin,
    xmax, ymax, zmax;
  
 
};

  
#endif

 
